fn s(a: &[u8], b: bool) -> Vec<u32> {
    let c = a.len();
    let d = (c + 3) / 4;
    let mut v = if b {vec![0; d + 1]} else {vec![0; d]};
    for i in 0..c {
        v[i / 4] |= (a[i] as u32) << (i % 4 * 8);
    }
    if b {
        v[d] = c as u32;
    }
    v
}

fn l(a: &[u32], b: bool) -> Vec<u8> {
    let d = a.len();
    let mut c = if b {(d - 1) * 4} else {d * 4};
    if b {
        let m = a[d - 1] as usize;
        if (m < c - 3) || (m > c) {
            return vec![];
        }
        c = m;
    }
    let mut v = vec![0 as u8; c];
    for i in 0..c {
        v[i] = (a[i / 4] >> (i % 4 * 8) & 0xff) as u8;
    }
    v
}

fn encode_bytes(data: &[u8], key: &[u8]) -> Vec<u8> {
    if data.is_empty() {
        return vec![];
    }
    let mut v = s(data, true);
    let mut k = s(key, false);
    if k.len() < 4 {
        k.resize(4, 0);
    }
    let n = v.len() - 1;
    let q = 52 / v.len() + 6;
    let mut z = v[n];
    let mut d = 0 as u32;
    for _ in 0..q {
        d = d.wrapping_add(2654435769);
        let e = (d >> 2 & 3) as usize;
        for i in 0..n {
            // println!("{}", i);
            let y = v[i + 1];
            // println!("{}", y);
            let m = ((z >> 5) ^ (y << 2)).wrapping_add(
                             (y >> 3) ^ (z << 4) ^ d ^ y).wrapping_add(
                                 k[(i & 3) ^ e] ^ z);
            // println!("{}", m);
            v[i] = v[i].wrapping_add(m);
            z = v[i];
            // println!("{}", z);
        }
        let y = v[0];
        let m = ((z >> 5) ^ (y << 2)).wrapping_add(
                         (y >> 3) ^ (z << 4) ^ d ^ y).wrapping_add(
                             k[(n & 3) ^ e] ^ z);
        v[n] = v[n].wrapping_add(m);
        z = v[n];
    }
    l(&v, false)
}

pub fn encode(data: &str, key: &str) -> Vec<u8> {
    encode_bytes(data.as_bytes(), key.as_bytes())
}
